package com.spring.housing1.server;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.google.zxing.WriterException;
import com.spring.housing1.constant.Constants;
import com.spring.housing1.pojo.AppointmentInfo;
import com.spring.housing1.pojo.CardInfo;
import com.spring.housing1.pojo.DoctorInfo;
import com.spring.housing1.returnType.CommenResult;
import com.spring.housing1.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Service
public class ExecutorServer {
    @Value("${grant_type}")
    public String grant_type;
    @Value("${AppSecret}")
    public String AppSecret;
    @Value("${appId}")
    public String appId;


    private final Logger log = LoggerFactory.getLogger(ExecutorServer.class);
    @Qualifier("Db1Template")
    @Autowired
    JdbcTemplate jdbcTemplate;


    public CommenResult<Object> doLogin(Map<String, String> param, HttpSession httpSession) throws Exception {

//登录时没有该用户则新增，登录过的用户查询相应信息。
        CommenResult res = new GeiWxPhone().getPhone(grant_type, AppSecret, appId, param.get("code"), jdbcTemplate);
        String sql = "insert  into wx_user set open_id = ?";
        String q_sql = "select  count(*) from wx_user where open_id = ?";
        if (res.getStatus() == 200) {
//            将token设置到session中

            Object data = res.getData();
            Map m = (Map<String, String>) data;
//             判断数据库刘是否有该用户存在open_id去做唯一标识
            Map<String, Object> maps = jdbcTemplate.queryForMap(q_sql, m.get("openid"));
//            没有用户自动新增,有该用户则跳过
            if (Integer.parseInt(maps.get("count(*)").toString()) == 0) {
                jdbcTemplate.update(sql, m.get("openid"));
                Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap("select sex,phone from wx_user where open_id =? ",m.get("openid"));
             Map<String,Object> ress = new ConcurrentHashMap<>();
                ress.put("params",res.getData());
                ress.put("userInfo",stringObjectMap);
                return new CommenResult<>(200,"success",ress);
            }else{
                Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap("select sex,phone from wx_user where open_id =? ",m.get("openid"));
                Map<String,Object> ress = new ConcurrentHashMap<>();
                ress.put("params",res.getData());
                ress.put("userInfo",stringObjectMap);
                return new CommenResult<>(200,"success",ress);
            }

        }else{
            return new CommenResult<>(500,"获取用户信息失败!","");
        }

    }

    public CommenResult<Object> getCards(CardInfo cardInfo) {
        String sql = "select * from wx_card where open_id = ? " + " and enable =1";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, cardInfo.getOpen_id());
        if (maps.size() == 0) {
            return new CommenResult<>(200, "暂无就诊卡信息,请添加就诊卡", maps);
        }
        return new CommenResult<>(200, "查询成功!", maps);
    }


    @Transactional(rollbackFor = Exception.class)
    public CommenResult<Object> insertCards(Map<String, String> cardInfo) {
//        判断有无新增过的卡片，这里以身份证号作为唯一区分
        {
            String sql = "select count(*) from wx_card where open_id = ? and identify_id =?" ;
            List list = MapUtils.mapToList(cardInfo, "open_id", "identify_id");

            Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap(sql, list.toArray());
            if(Integer.parseInt(stringObjectMap.get("count(*)").toString()) >0){
                return   new CommenResult<>(201, "新增失败，改卡片已添加", "~");
            }
        }

        {
//        卡没有设置为默认卡时直接写入数据库
            if (cardInfo.get("defaults").equals("0")) {
                String sql = " insert into wx_card(real_name,open_id,cell_phone,identify_id,defaults,enable,sex) values(?,?,?,?,?,?,?) ";
//      将map加入sql注入参数中
                List list = MapUtils.mapToList(cardInfo, "real_name", "open_id", "cell_phone", "identify_id", "defaults", "enable", "sex");
                jdbcTemplate.update(sql, list.toArray());
                return new CommenResult<>(200, "新增就诊卡信息成功!", "~");
            } else {
//        有其他的默认卡先将其他的默认卡更改为非默认状态再新增
                String up_sql = " update wx_card set defaults = 0 where open_id =? ";
                jdbcTemplate.update(up_sql, cardInfo.get("open_id"));
                //      将map加入sql注入参数中
                List list = MapUtils.mapToList(cardInfo, "real_name", "open_id", "cell_phone", "identify_id", "defaults", "enable", "sex");
//        插入数据
                String ins_sql = " insert into wx_card(real_name,open_id,cell_phone,identify_id,defaults,enable,sex) values(?,?,?,?,?,?,?) ";
                jdbcTemplate.update(ins_sql, list.toArray());
                return new CommenResult<>(200, "新增就诊卡信息成功!", "~");
            }
        }
    }

    public CommenResult<Object> updateCards(Map<String, String> cardInfo) {
        String up_sql = " update wx_card set enable = 0  where  open_id =? and  identify_id =? ";
        jdbcTemplate.update(up_sql, cardInfo.get("open_id"),  cardInfo.get("identify_id"));
        return new CommenResult<>(200, "删除诊卡信息成功!", "~");
    }

    /*
     * 并发获取号码
     * */
    public synchronized CommenResult<Object> getAppointment(AppointmentInfo appointmentInfo) throws Exception {

        synchronized (this) {
//            锁定当前会话的sql执行

            Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap(" select count(*)  from numbers where enable !=0;");
            Map<String, Object> count = jdbcTemplate.queryForMap(" select count(*)  from ctp_aff where enable =0   and open_id = ? and identify_id = ?",appointmentInfo.getCardInfo().getOpen_id(),appointmentInfo.getCardInfo().getIdentify_id());
            if (stringObjectMap.get("count(*)") == Constants.maxNum) {
                log.info("请稍后重试，排队人太多了~");
                return new CommenResult<>(201, "请稍后重试，排队人太多了~", "");
            }

            if (Integer.parseInt(count.get("count(*)").toString()) >= 1) {
                log.info("已在队列中~");
                return new CommenResult<>(201, "已排队~", "");
            }
            Map<String, Object> stringObjectMap1 = jdbcTemplate.queryForMap("select num  from numbers where enable =0 ORDER BY num  limit 1;");
//            流程id
            String node_id =cn.hutool.core.lang.UUID.randomUUID().toString().replaceAll("-","");
            jdbcTemplate.update("update numbers set  enable = 1, times =?,open_id =?,node_id =?,front =?  where num =" + stringObjectMap1.get("num"), new Date(),appointmentInfo.getCardInfo().getOpen_id(),node_id,stringObjectMap.get("count(*)").toString());
            AppointmentInfo appointmentInfo1 = new AppointmentInfo();
            //            前面几人
            appointmentInfo1.setBeforeNum(stringObjectMap.get("count(*)").toString());
            //            预约号码
            appointmentInfo1.setAppointmentNum(stringObjectMap1.get("num").toString());
//            按次序分配医师
            DoctorInfo doct = GetDoctorInfo.getDoct(jdbcTemplate);
            appointmentInfo1.setDoctorInfo(doct);
//            纠正卡信息
            appointmentInfo1.setCardInfo(appointmentInfo.getCardInfo());
//            就诊部位
            appointmentInfo1.setType(appointmentInfo.getType());
//            新增流程信息到影像医生
            List arr = new ArrayList();
            arr.add(appointmentInfo.getCardInfo().getReal_name()+"_"+appointmentInfo.getType());
            arr.add(appointmentInfo.getCardInfo().getCell_phone());
            arr.add(new Date());
            arr.add("0");
            arr.add(doct.getId());
            arr.add(node_id);
            arr.add(appointmentInfo.getCardInfo().getOpen_id());
            arr.add(appointmentInfo.getCardInfo().getIdentify_id());
            jdbcTemplate.update("insert into ctp_aff(patient,cell_phone,apply_time,enable,doctor_id,node_id,open_id,identify_id) values(?,?,?,?,?,?,?,?)",arr.toArray());
            log.info("当前号码为:" + stringObjectMap1.get("num") + "前面有:" + stringObjectMap.get("count(*)") + "人");
            return new CommenResult<>(200, "用户: " + appointmentInfo.getCardInfo().getReal_name() + "的当前号码为:" + stringObjectMap1.get("num") + "前面有:" + stringObjectMap.get("count(*)") + "人", appointmentInfo1);
        }
    }


    public CommenResult<Object> getUserInfos(String param) {
        Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap("select * from wx_user where open_id =? ",param);
    return  new CommenResult<>(200,"获取用户信息成功",stringObjectMap);
    }

    public CommenResult<Object> modifyCards(Map<String, String> cardInfo) {

        //是否修改为默认卡片前判断是否有该字段修改,修改为默认卡片时先将所有该类型卡牌设为非默认
        Optional.ofNullable(cardInfo.get("defaults")).ifPresent(param->{
            if(Integer.parseInt(param)==1){
                jdbcTemplate.update("update wx_card set defaults = 0 where open_id =?  ",cardInfo.get("open_id"));

            }
        });

        String up_sql = " update wx_card  set open_id = ? ";
         List arr = new ArrayList();
        arr.add(cardInfo.get("open_id"));

        if(cardInfo.get("real_name") == null ? false : true){
            up_sql += " , real_name = ? ";
            arr.add(cardInfo.get("real_name"));
        }
        if(cardInfo.get("cell_phone") == null ? false : true){
            up_sql += ",  cell_phone = ? ";
            arr.add(cardInfo.get("cell_phone"));
        }
        if(cardInfo.get("identify_id") == null ? false : true){
            up_sql += " , identify_id = ? ";
            arr.add(cardInfo.get("identify_id"));
        }
        if(cardInfo.get("defaults") == null ? false : true){
            up_sql += " , defaults = ? ";
            arr.add(cardInfo.get("defaults"));
        }
        if(cardInfo.get("sex") == null ? false : true){
            up_sql += " , sex = ? ";
            arr.add(cardInfo.get("sex"));
        }
        up_sql +=" where   open_id =? and  identify_id =? ";
        arr.add(cardInfo.get("open_id"));
        arr.add(cardInfo.get("identify_id"));
        jdbcTemplate.update(up_sql, arr.toArray());


        return new CommenResult<>(200, "修改就诊卡信息成功!", "~");
    }
    @Transactional(rollbackFor = Exception.class)
    public CommenResult<Object> cancelAppointment(Map<String, String> appointmentInfo) {

//        流程撤销
        int node_id = jdbcTemplate.update("update ctp_aff set  enable = 3  where node_id = ? and enable = 0 ", appointmentInfo.get("node_id"));
        if(node_id >0){
            //        号码回收
            jdbcTemplate.update("update numbers set  enable = 0, times =? , open_id = ?,node_id =? ,front =? where node_id =? " ,null,null,null,null,appointmentInfo.get("node_id"));
            return new CommenResult<>(200,"撤销成功!" ,"");
        }else{
            return new CommenResult<>(201,"撤销失败!受理中..." ,"");
        }

    }

    public String getCodeImages(Map<String, String> param) throws Exception {
        String sql = "select * from wx_card where open_id = ?  and identify_id = ? " + " and enable =1";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, param.get("open_id"),param.get("identify_id"));
        String s = JSONUtil.toJsonStr(maps.get(0));
//        小程序单页
        String url ="http://xxxxxxxxxxxx/danye/index.html?data=" +s;

        BufferedImage bufferedImage = CodeUtil.getBufferedImage(url);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            // 设置图片格式
            ImageIO.write(bufferedImage, "png", stream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        byte[] encode = Base64.getEncoder().encode(stream.toByteArray());

        String base64 = new String(encode);
        return base64;
    }


    public CommenResult<Object> getAppointmentInfo(Map<String, String> appointmentInfo) {
        String sql ="select * from (select a.num,a.times,a.front,b.patient,b.identify_id,b.sex,b.node_id,\n" +
                "b.name,b.real_name,b.dim_time,b.descs,b.room,b.open_id from\n" +
                "(select  num,times,node_id node,front,node_id  from numbers where enable = 1)a  \n" +
                "\n" +
                "inner join \n" +
                "\n" +
                "(select a.patient,a.identify_id,a.sex,a.node_id,a.open_id,\n" +
                "b.name,b.real_name,b.dim_time,b.descs,b.room from\n" +
                "(\n" +
                "select SUBSTRING_INDEX(a.patient,\"_\",1)patient,a.identify_id,a.sex,a.doctor_id,a.node_id,a.open_id from (\n" +
                "select a.*,b.phone,b.sex  from \n" +
                "(select * from  ctp_aff  where enable = 0)a \n" +
                "left join (select cell_phone phone,sex,open_id,identify_id from wx_card)b\n" +
                "on a.open_id =b.open_id and a.identify_id=b.identify_id)a)a\n" +
                "\n" +
                "inner join\n" +
                "\n" +
                "(select a.name,a.real_name,a.dim_time,b.descs,b.room,a.id from \n" +
                " (select id,name,real_name,room_id,dim_time from  web_mana_user where enable = 1 and room_id = 2)a\n" +
                "\n" +
                "left join (\n" +
                "select room_id,descs,room from room where enable=1)b\n" +
                "on a.room_id =b.room_id)b\n" +
                "on a.doctor_id = b.id)b\n" +
                "on a.node = b.node_id)a \n" +
                "  where open_id =  ?";

        List<Map<String, Object>> res = jdbcTemplate.queryForList(sql, appointmentInfo.get("open_id"));
        log.info("当前sql为:{}",sql);
        return new CommenResult<>(200,"查询成功!" ,res);
    }
    @Transactional(rollbackFor = Exception.class)
    public CommenResult<Object> getCdInfo(Map<String, String> appointmentInfo) {
        String sql ="select * from (select a.*,case when b.doctor2_name ='' or b.doctor2_name is null then '未开始' else b.doctor2_name end as doctor2_name,\n" +
                "case when b.deal_result ='' or b.deal_result is null then '未开始' else b.deal_result end as deal_result \n" +
                "\n" +
                "-- 影像医生处理信息结果\n" +
                " from (select a.patient,a.identify_id,a.sex,a.node_id,a.open_id,a.cd_result,a.type,a.apply_time,a.img_path ,a.enable ,a.remark,\n" +
                "b.real_name doctor_name  from\n" +
                "(\n" +
                "select SUBSTRING_INDEX(a.patient,\"_\",1)patient,SUBSTRING_INDEX(a.patient,\"_\",-1)type,a.identify_id,a.sex,a.doctor_id,a.node_id,a.open_id,a.apply_time,a.cd_result,a.img_path,a.enable,a.remark from (\n" +
                "select a.*,b.phone,b.sex  from \n" +
                "(select * from  ctp_aff  where enable = 2 or enable = 1 or enable = 4 or enable = 5 )a \n" +
                "left join (select phone,sex,open_id from wx_user)b\n" +
                "on a.open_id =b.open_id)a)a\n" +
                "\n" +
                "inner join\n" +
                "\n" +
                "(select a.name,a.real_name,a.dim_time,b.descs,b.room,a.id from \n" +
                " (select id,name,real_name,room_id,dim_time from  web_mana_user where enable = 1 and room_id = 2 )a\n" +
                "\n" +
                "left join (\n" +
                "select room_id,descs,room from room where enable=1)b\n" +
                "on a.room_id =b.room_id)b\n" +
                "on a.doctor_id = b.id)a  \n" +
                "\n" +
                "left join\n" +
                "-- 内外科医生处理信息结果\n" +
                "(\n" +
                "select a.*,\n" +
                "b.real_name doctor2_name  from\n" +
                "(select doctor2_id,deal_result,node_id from  ctp_aff  where enable = 1 )a \n" +
                "\n" +
                "\n" +
                "inner join\n" +
                "\n" +
                "(select a.name,a.real_name,a.dim_time,b.descs,b.room,a.id from \n" +
                " (select id,name,real_name,room_id,dim_time from  web_mana_user where enable = 1 and room_id = 3)a\n" +
                "\n" +
                "left join (\n" +
                "select room_id,descs,room from room where enable=1)b\n" +
                "on a.room_id =b.room_id)b\n" +
                "on a.doctor2_id = b.id\n" +
                ")b\n" +
                "on a.node_id = b.node_id)a where node_id = ?";
//        设置消息状态为已查看
        jdbcTemplate.update("update ctp_aff set view = 1 where node_id = ?",appointmentInfo.get("node_id"));
        List<Map<String, Object>> res = jdbcTemplate.queryForList(sql, appointmentInfo.get("node_id"));
        log.info("当前sql为:{}",sql);
        return new CommenResult<>(200,"查询成功!" ,res);
    }

    public CommenResult<Object> udateAppointmentInfo() {
        String sql ="select  num,enable,times,open_id,node_id,front from  numbers where enable = 1 order by times ";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        for (int i = 0; i <maps.size() ; i++) {
           jdbcTemplate.update("update numbers set front =? where num =? and open_id=? and node_id =?",i,maps.get(i).get("num"),maps.get(i).get("open_id"),maps.get(i).get("node_id"));
        }
        return new CommenResult<>(200,"更新成功!" , DateUtils.format(new Date(),DateUtils.DATETIME_PATTERN5));
    }

    public CommenResult<Object> getReportList(Map<String, String> appointmentInfo) {
        String sql ="select  SUBSTRING_INDEX(patient,\"_\",1)as patient,SUBSTRING_INDEX(patient,\"_\",-1) as type ,DATE_FORMAT(apply_time,'%Y-%m-%d')apply_time,node_id  from ctp_aff where enable in (1,2,4,5) " +
                "  and  open_id =?  order by apply_time desc";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql,appointmentInfo.get("open_id"));
        return new CommenResult<>(200,"查询成功!" , maps);
    }

    public CommenResult<Object> modifyUsersInfo(Map<String, String> cardInfo) {

        String sql ="update wx_user ";
        List list = MapUtils.mapKeyToList(cardInfo, "phone", "wx_name", "sex");
        if(ObjectUtil.isEmpty(list)){
            return new CommenResult<>(200,"没有任何更新" , DateUtils.format(new Date(),DateUtils.DATETIME_PATTERN5));
        }else {
            List<String> param = new ArrayList<>();
            int j = 0;
            for (int i = 0; i < list.size(); i++) {
                if (j == 0) {
                    param.add(cardInfo.get(list.get(i)));
                    sql += (" set  " + list.get(i) + " = ? ");
                    j++;
                } else {
                    param.add(cardInfo.get(list.get(i)));
                    sql += (" ," + list.get(i) + " = ? ");
                }
            }
            sql += (" where open_id = ? ");
            log.info(sql);
            param.add(cardInfo.get("open_id"));
            jdbcTemplate.update(sql, param.toArray());
            return new CommenResult<>(200, "个人信息更新成功!", DateUtils.format(new Date(), DateUtils.DATETIME_PATTERN5));
        }
    }


    public CommenResult<Object> queryRoleDoctor(Map<String, String> param) {
        String sql = "select a.* from \n" +
                "(select a.id ,a.name,a.user_name,a.real_name,a.cell_phone,a.dim_time,a.enable,b.room,b.room_id from \n" +
                "(select id ,name,real_name,user_name,cell_phone,dim_time,enable,room_id  from  web_mana_user where room_id =3) a\n" +
                "left join room  b on\n" +
                "b.room_id = a.room_id  )a where 1=1 ";
        List params = new ArrayList<String>();
            sql +=" and enable = 1 ";

        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, params.toArray());

        return new CommenResult<>(200,"查询医生信息成功!",maps);
    }


    public CommenResult<Object> askDoctir(Map<String, String> param) {
String sql ="update ctp_aff set enable = 4,remark =?,doctor2_id =? where node_id = ?  ";
        jdbcTemplate.update(sql, param.get("remark"),param.get("doctor2_id"),param.get("node_id"));
        return new CommenResult<>(200,"询问内外科医生成功!","");
    }

    public CommenResult<Object> cancelDeal(Map<String, String> appointmentInfo) {

    int node_id=    jdbcTemplate.update("update ctp_aff set  enable = 5  where node_id = ? and enable = 4 ", appointmentInfo.get("node_id"));
        if(node_id >0){
            return new CommenResult<>(200,"撤销成功!" ,"");
        }else{
            return new CommenResult<>(201,"撤销失败!受理中..." ,"");
        }
    }

    public CommenResult<Object> queryMessage(Map<String, String> param) {

        String sql ="select  SUBSTRING_INDEX(patient,\"_\",1)as patient,SUBSTRING_INDEX(patient,\"_\",-1) as type ,DATE_FORMAT(apply_time,'%Y-%m-%d')apply_time,node_id  from ctp_aff where enable in (1,2,4) and view = 0 " +
                "  and  open_id =?  order by apply_time desc";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql,param.get("open_id"));
        return new CommenResult<>(200,"查询成功!" , maps);
    }
}
